﻿using System;
using System.Collections.Generic;
using System.Linq;
using HappyBa.Core.Data;
using HappyBa.Core.Interfaces;

namespace HappyBa.Core.Validators
{
    public class TasksAndBugsRelatedWithStory : IValidator
    {
        public IEnumerable<ValidationResult> Validate(ValidationContext context)
        {
            foreach (var entity in context.Metrics.UserStories.Where(x => x.Bugs.Any() && x.Tasks.Any()))
            {
                var childsDone = entity.Bugs.All(context.Metrics.IsFinished) && entity.Tasks.All(context.Metrics.IsFinished);
                if (!context.Metrics.IsFinished(entity) && childsDone && entity.Impediments.All(context.Metrics.IsResolved))
                {
                    yield return new ValidationResult(
                        string.Format("{0}: {1} should be Done, because all tasks and bugs are done ({2})", entity.EntityType.Name, entity.Id, GetEntityInfo(entity, context.Metrics)))
                    {
                        Entity = entity
                    };
                }
                else if (context.Metrics.IsFinished(entity) && (!childsDone || !entity.Impediments.All(context.Metrics.IsResolved)))
                {
                    yield return new ValidationResult(
                        string.Format("{0}: {1} shouldn't be Done, because some of the tasks or bugs are not done ({2})", entity.EntityType.Name, entity.Id, GetEntityInfo(entity, context.Metrics)))
                    {
                        Entity = entity
                    };
                }
            }
        }

        private static string GetEntityInfo(UIUserStory entity, IMetrics metrics)
        {
            var all = entity.Bugs.Cast<UIStatebleEntityBase>()
                .Concat(entity.Impediments)
                .Concat(entity.Tasks)
                .ToArray();
            if (!all.Any()) return string.Empty;
            var maxModify = all.Where(x=>x.ModifyDate.HasValue).OrderBy(x => x.ModifyDate).LastOrDefault();
            var maxCreate = all.Where(x=>x.StartDate.HasValue).OrderBy(x => x.StartDate.Value).LastOrDefault();
            var maxComment = all.Concat(new[] { entity }).SelectMany(x => x.Comments).OrderBy(y => y.CreateDate).LastOrDefault();
            if (maxModify == null && maxCreate == null && maxComment == null) return string.Empty;

            var maxItem = DateTime.MinValue;
            if (maxCreate != null && (maxModify == null || maxModify.ModifyDate < maxCreate.StartDate.Value))
            {
                maxModify = maxCreate;
                maxItem = maxCreate.StartDate.Value;
            }
            else
            {
                if (maxModify != null)
                {
                    maxItem = maxModify.ModifyDate.Value;
                }
            }

            if (maxModify == null || ( maxComment!=null && maxItem < maxComment.CreateDate))
            {
                return string.Format("{1} {0}:{2}", maxComment.CreateDate.ToShortDateString(), maxComment.Owner, maxComment.Description);
            }
            return string.Format("{1} {0} {2}", maxItem.ToShortDateString(), GetDeveloper(maxModify, metrics), maxModify);
        }

        private static string GetDeveloper(UIStatebleEntityBase entity, IMetrics metrics)
        {
            var item = entity as UIEstimatableEntityBase;
            if (item != null)
            {
                var dev = item.Assignments.FirstOrDefault(x => metrics.IsDeveloper(x.GeneralUser));
                if (dev != null) return dev.GeneralUser.ToString();
            }
            return entity.Owner.ToString();

        }
    }
}
